using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using RestaurantFinder.Core.Models;
using RestaurantFinder.Core.Services;

namespace RestaurantFinder.Infrastructure.Services;

/// <summary>
/// 智能餐厅服务 - 根据配置自动选择数据源
/// </summary>
public class SmartRestaurantService : IRestaurantService
{
    private readonly IGaodeMapService _gaodeMapService;
    private readonly ISearchCacheService _cacheService;
    private readonly IConfiguration _configuration;
    private readonly ILogger<SmartRestaurantService> _logger;

    public SmartRestaurantService(
        IGaodeMapService gaodeMapService,
        ISearchCacheService cacheService,
        IConfiguration configuration, 
        ILogger<SmartRestaurantService> logger)
    {
        _gaodeMapService = gaodeMapService;
        _cacheService = cacheService;
        _configuration = configuration;
        _logger = logger;
    }

    /// <summary>
    /// 搜索餐厅 - 智能数据源选择 + 缓存优化
    /// </summary>
    public async Task<List<Restaurant>> SearchRestaurantsAsync(Location userLocation, int radiusInMeters)
    {
        try
        {
            // 使用默认类别进行缓存查找，确保缓存键一致性
            const string defaultCategory = "餐饮服务";
            
            // 1. 首先尝试从缓存获取结果
            var cachedResult = await _cacheService.GetCachedSearchResultAsync(userLocation, radiusInMeters, defaultCategory);
            if (cachedResult != null)
            {
                _logger.LogInformation("🗃️ 从缓存返回 {Count} 家餐厅", cachedResult.Count);
                return cachedResult;
            }

            _logger.LogDebug("🔍 缓存未命中，开始新的搜索 - 位置: ({Lat}, {Lng}), 半径: {Radius}米", 
                userLocation.Latitude, userLocation.Longitude, radiusInMeters);

            // 2. 检查是否启用高德地图API
            var enabledSection = _configuration.GetSection("GaodeMap:Enabled");
            var isGaodeEnabled = bool.TryParse(enabledSection.Value, out var enabled) && enabled;
            var hasApiKey = !string.IsNullOrEmpty(_configuration["GaodeMap:ApiKey"]);

            List<Restaurant> restaurants;

            if (isGaodeEnabled && hasApiKey)
            {
                // 3. 使用高德地图API搜索
                _logger.LogInformation("🗺️ 使用高德地图API搜索餐厅");
                restaurants = await SearchWithGaodeMapAsync(userLocation, radiusInMeters);
            }
            else
            {
                // 4. 使用模拟数据
                _logger.LogInformation("🎭 使用模拟数据搜索餐厅");
                restaurants = await SearchWithMockDataAsync(userLocation, radiusInMeters);
            }

            // 5. 缓存搜索结果（使用与查询时相同的category）
            if (restaurants.Any())
            {
                await _cacheService.SetCachedSearchResultAsync(userLocation, radiusInMeters, restaurants, defaultCategory);
                _logger.LogDebug("💾 已缓存 {Count} 家餐厅到位置: ({Lat}, {Lng})", 
                    restaurants.Count, userLocation.Latitude, userLocation.Longitude);
            }

            _logger.LogInformation("🔍 搜索完成，找到 {Count} 家餐厅", restaurants.Count);
            return restaurants;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "搜索餐厅时发生错误");
            return new List<Restaurant>();
        }
    }

    /// <summary>
    /// 使用高德地图API搜索（带重试机制）
    /// </summary>
    private async Task<List<Restaurant>> SearchWithGaodeMapAsync(Location userLocation, int radiusInMeters)
    {
        var allRestaurants = new List<Restaurant>();
        var searchKeywords = new[] { "美食", "餐厅", "饭店", "小吃" };

        foreach (var keyword in searchKeywords)
        {
            try
            {
                var request = new RestaurantSearchRequest
                {
                    Location = userLocation,
                    RadiusInMeters = radiusInMeters,
                    Keyword = keyword,
                    MaxResults = 10
                };

                var response = await _gaodeMapService.SearchPoisAsync(request);
                
                if (response.Status == "1" && response.Pois?.Any() == true)
                {
                    var restaurants = _gaodeMapService.ConvertToRestaurants(response.Pois, userLocation);
                    allRestaurants.AddRange(restaurants);
                    _logger.LogDebug("🔍 关键词 '{Keyword}' 找到 {Count} 家餐厅", keyword, restaurants.Count);
                }
                else
                {
                    _logger.LogWarning("⚠️ 高德地图API调用失败: {Status} - {Info}", response.Status, response.Info);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "使用关键词 '{Keyword}' 搜索时发生错误", keyword);
            }
        }

        // 去重并按距离排序
        var uniqueRestaurants = allRestaurants
            .GroupBy(r => r.Id)
            .Select(g => g.First())
            .OrderBy(r => r.Distance)
            .Take(50)
            .ToList();

        _logger.LogInformation("🗺️ 高德地图API总共找到 {Count} 家独特餐厅", uniqueRestaurants.Count);
        return uniqueRestaurants;
    }

    /// <summary>
    /// 使用模拟数据搜索
    /// </summary>
    private async Task<List<Restaurant>> SearchWithMockDataAsync(Location userLocation, int radiusInMeters)
    {
        await Task.Delay(100); // 模拟网络延迟

        // 创建模拟餐厅，并正确计算距离
        var mockRestaurants = new List<Restaurant>();
        
        var restaurants = new[]
        {
            new { Name = "老北京炸酱面馆", Address = "朝阳区建国路88号", LatOffset = 0.001, LngOffset = 0.001, Rating = 4.5, Phone = "010-12345678" },
            new { Name = "川香小厨", Address = "海淀区中关村大街100号", LatOffset = 0.002, LngOffset = -0.001, Rating = 4.2, Phone = "010-87654321" },
            new { Name = "粤味茶餐厅", Address = "西城区西单北大街50号", LatOffset = -0.001, LngOffset = 0.002, Rating = 4.7, Phone = "010-11223344" },
            new { Name = "东北饺子王", Address = "丰台区南三环西路200号", LatOffset = 0.003, LngOffset = 0.003, Rating = 4.0, Phone = "010-55667788" },
            new { Name = "江南小笼包", Address = "东城区王府井大街168号", LatOffset = -0.002, LngOffset = -0.002, Rating = 4.6, Phone = "010-99887766" },
            new { Name = "成都火锅", Address = "海淀区学院路50号", LatOffset = 0.0015, LngOffset = 0.0005, Rating = 4.3, Phone = "010-66778899" },
            new { Name = "广式茶点", Address = "朝阳区三里屯路10号", LatOffset = -0.0005, LngOffset = 0.0015, Rating = 4.4, Phone = "010-55443322" }
        };

        for (int i = 0; i < restaurants.Length; i++)
        {
            var restaurant = restaurants[i];
            var restaurantLocation = new Location(
                userLocation.Latitude + restaurant.LatOffset, 
                userLocation.Longitude + restaurant.LngOffset);
            
            // 计算实际距离（米）
            var distance = CalculateDistance(userLocation, restaurantLocation);
            
            mockRestaurants.Add(new Restaurant(
                Id: (i + 1).ToString(),
                Name: restaurant.Name,
                Address: restaurant.Address,
                Location: restaurantLocation,
                Distance: distance,
                Rating: restaurant.Rating,
                PhoneNumber: restaurant.Phone
            ));
        }

        // 根据搜索半径过滤
        var filteredRestaurants = mockRestaurants
            .Where(r => r.Distance <= radiusInMeters)
            .OrderBy(r => r.Distance)
            .ToList();

        _logger.LogInformation("🎭 模拟数据返回 {Count} 家餐厅（搜索半径: {Radius}米）", 
            filteredRestaurants.Count, radiusInMeters);
        
        return filteredRestaurants;
    }

    /// <summary>
    /// 计算两点间距离（米）- 使用Haversine公式
    /// </summary>
    private static double CalculateDistance(Location point1, Location point2)
    {
        const double earthRadius = 6371000; // 地球半径（米）
        
        var lat1Rad = point1.Latitude * Math.PI / 180;
        var lat2Rad = point2.Latitude * Math.PI / 180;
        var deltaLatRad = (point2.Latitude - point1.Latitude) * Math.PI / 180;
        var deltaLonRad = (point2.Longitude - point1.Longitude) * Math.PI / 180;

        var a = Math.Sin(deltaLatRad / 2) * Math.Sin(deltaLatRad / 2) +
                Math.Cos(lat1Rad) * Math.Cos(lat2Rad) *
                Math.Sin(deltaLonRad / 2) * Math.Sin(deltaLonRad / 2);
        
        var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        
        return earthRadius * c;
    }

    /// <summary>
    /// 从餐厅列表中随机选择一家
    /// </summary>
    /// <param name="restaurants">餐厅列表</param>
    /// <returns>随机选择的餐厅，如果列表为空则返回null</returns>
    public Restaurant? SelectRandomRestaurant(IList<Restaurant> restaurants)
    {
        if (restaurants == null || restaurants.Count == 0)
        {
            _logger.LogWarning("⚠️ 餐厅列表为空，无法随机选择");
            return null;
        }

        var random = new Random();
        var selectedIndex = random.Next(restaurants.Count);
        var selectedRestaurant = restaurants[selectedIndex];
        
        _logger.LogInformation("🎲 随机选择了餐厅: {Name} (第 {Index}/{Total} 个)", 
            selectedRestaurant.Name, selectedIndex + 1, restaurants.Count);
        
        return selectedRestaurant;
    }
} 